package com.ruoyi.business.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.bizsys.domain.*;
import com.ruoyi.bizsys.mapper.AppUserMapper;
import com.ruoyi.bizsys.mapper.IncreasedLimitListMapper;
import com.ruoyi.bizsys.service.IAppUserMarkService;
import com.ruoyi.bizsys.service.ICustomerInfoService;
import com.ruoyi.bizsys.utils.BizConstants;
import com.ruoyi.business.common.AsyncService;
import com.ruoyi.business.mapper.BCreditAccountMapper;
import com.ruoyi.business.service.ICreditAccountInfoService;
import com.ruoyi.common.constant.RiskConstants;
import com.ruoyi.common.utils.Func;
import com.ruoyi.common.utils.ObjectUtil;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.sms.domain.SmsSendData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 账户信息Service业务层处理
 *
 * @author african-loan
 * @date 2021-03-15
 */
@Service
@Slf4j
public class CreditAccountInfoServiceImpl implements ICreditAccountInfoService {

    @Autowired
    BCreditAccountMapper creditAccountMapper;

    @Autowired
    IncreasedLimitListMapper increasedLimitListMapper;

    @Autowired
    AppUserMapper appUserMapper;

    @Autowired
    AsyncService asyncService;

    @Autowired
    IAppUserMarkService appUserMarkService;

    @Autowired
    private ICustomerInfoService customerInfoService;

    /**
     * 根据客户id查找授信 多个逗号分隔
     *
     * @param custNos
     * @return
     */
    @Override
    public List<CreditAccount> findInCustNos(String custNos) {
        return creditAccountMapper.findInCustNos(custNos);
    }

    /**
     * 批量更新当前额度
     */
    @Override
    public void updateCreditLineBatch(List<CreditAccount> list) {
        List<CreditAccount> creditAccountList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            creditAccountList.add(list.get(i));
            if ((i + 1) % 1000 == 0||i == list.size() - 1) {
                creditAccountMapper.updateCreditLineBatch(creditAccountList);
                creditAccountList = new ArrayList<CreditAccount>();
            }
        }
    }


    @Override
    public boolean updateCustomerByRuleResult(JSONObject ruleRst, String custNo, String type) {
        // 接收审批结果，更新客户信息
        String approveFlag = ruleRst.getString(RiskConstants.RULE_RESULT_DEAL_TYPE_KEY);
        CustomerInfo customerInfo = new CustomerInfo();
        customerInfo.setCustNo(custNo);
        //通过
        if (StringUtils.equals(approveFlag, RiskConstants.RULE_RESULT_PASS)) {
            //测算额度
            customerInfo.setPreLine(ruleRst.getString(RiskConstants.RULE_PASS_PRE_LINE));
        }
        //是否可主动提额
        customerInfo.setPromotion(ruleRst.getString(RiskConstants.RULE_PROMOTION));
        //征信有效期
        customerInfo.setExpiryDate(ruleRst.getString(RiskConstants.RULE_CREDIT_EXPIRY_DATE));
        //模型评级
        customerInfo.setModelLevel(ruleRst.getString(RiskConstants.RULE_MODEL_LEVEL));
        //授信模型评级
        customerInfo.setCreditModelLevel(ruleRst.getString(RiskConstants.RULE_CREDIT_MODEL_LEVEL));
        //信用评级 只在通过/拒绝的时候保存（来自需求）
        String rating = ruleRst.getString(RiskConstants.RULE_CREDIT_RATING);
        if (StringUtils.equalsAny(approveFlag, RiskConstants.RULE_RESULT_PASS, RiskConstants.RULE_RESULT_REJECT)
                && Func.isNotEmpty(rating) && !"-1".equals(rating)) {
            customerInfo.setCreditRating(rating);
        }
        //授信的时候更新
        String bindCardNum = ruleRst.getString(RiskConstants.RULE_NEED_BIND_CARD_NUM);
        log.info("bindCardNum:{}:{}", bindCardNum, type);
        if (RiskConstants.RULE_TYPE_APPLY.equals(type) && Func.isNotEmpty(bindCardNum)) {
            customerInfo.setNeedBindCardNum(Integer.parseInt(bindCardNum));
        }

        return customerInfoService.updateByCustNo(customerInfo);
//        return restTemplateService.updateExpiryDate(customerInfo);

    }

    /**
     * 导入提额名单
     */
    @Transactional
    @Override
    public List<Object> importFile(List<IncreasedLimitList> list) {
        List<Object> errorMsgList = new ArrayList<>();

        //custNo剔除重复数据
        List<String> custNos = list.stream().map(p -> p.getCustNo()).collect(Collectors.toList());
        List<String> duplicateList = custNos.stream().collect(Collectors.collectingAndThen(Collectors
                .groupingBy(Function.identity(), Collectors.counting()), map -> {
            map.values().removeIf(size -> size == 1);
            List<String> tempList = new ArrayList<>(map.keySet());
            return tempList;
        }));
        if (ObjectUtil.isNotEmpty(duplicateList)) {
            for (String duplicate : duplicateList) {
                list.removeIf(e -> e.getCustNo().equals(duplicate));
                errorMsgList.add("custNo=" + duplicate + "重复");
            }
            if (list.isEmpty()) {
                return errorMsgList;
            }
        }

        //检查必填表格字段
        Iterator<IncreasedLimitList> iterator = list.iterator();
        while (iterator.hasNext()) {
            IncreasedLimitList il = iterator.next();
            if (!checkThisObjEmpty(il)) {
                errorMsgList.add("custNo=" + il.getCustNo() + "缺少必填参数");
                iterator.remove();
            }
        }

        if (list.isEmpty()) {
            return errorMsgList;
        }
        //检查批次号是否错误
        if (!checkBatchNo(list)) {
            errorMsgList.add("批次号 batch_no错误");
            return errorMsgList;
        }

        //检查批次号是否已经提交
        IncreasedLimitList increasedLimitList = new IncreasedLimitList();
        increasedLimitList.setBatchNo(list.get(0).getBatchNo());
        List<IncreasedLimitList> listList = increasedLimitListMapper.selectIncreasedLimitListList(increasedLimitList);
        if (ObjectUtil.isNotEmpty(listList)) {
            errorMsgList.add("批次号 batch_no=" + list.get(0).getBatchNo() + "已经提交提额");
            return errorMsgList;
        }

        //解析文件得到的custNos去查询授信额度
        custNos = list.stream().map(p -> p.getCustNo()).collect(Collectors.toList());
        String custNosStr = StringUtils.join(custNos.toArray(), ",");
        List<CreditAccount> creditAccountList = findInCustNos(custNosStr);
        if (creditAccountList == null || creditAccountList.isEmpty()) {
            errorMsgList.add("找不到客户数据");
            return errorMsgList;
        }
        //检查custNos是否存在
        List<String> custNosCreditAccount = creditAccountList.stream().map(p -> p.getCustNo()).collect(Collectors.toList());
        for (String custNo : custNos) {
            if (!custNosCreditAccount.contains(custNo)) {
                errorMsgList.add("custNo=" + custNo + "不存在此客户");
                list.removeIf(e -> e.getCustNo().equals(custNo));
            }
        }
        if (list.isEmpty()) {
            return errorMsgList;
        }

        //检查提额前额度是否与数据库当前额度相同,提额后额度要大于提额前额度
        for (CreditAccount cAccount : creditAccountList) {
            Iterator<IncreasedLimitList> iter = list.iterator();
            while (iter.hasNext()) {
                IncreasedLimitList il = iter.next();
                if (cAccount.getCustNo().equals(il.getCustNo())
                        && cAccount.getCreditLine().compareTo(new BigDecimal(il.getCurrentCreditLine())) != 0) {
                    iter.remove();
                    errorMsgList.add("custNo=" + il.getCustNo() + "提额前额度错误");
                }
                BigDecimal currentCreditLine = new BigDecimal(il.getCurrentCreditLine());//提额前额度
                BigDecimal increasedCreditLine = new BigDecimal(il.getIncreasedCreditLine());//提额后额度
                if (currentCreditLine.compareTo(increasedCreditLine) > -1) {
                    iter.remove();
                    errorMsgList.add("custNo=" + il.getCustNo() + "提额后额度要大于提额前额度");
                }
            }
        }
        if (list.isEmpty()) {
            return errorMsgList;
        }
        //插入提额名单
        increasedLimitListMapper.insertBatch(list);

        //插入提额名单日志
        List<IncreasedLimitLog> illList = new ArrayList<>();
        List<AppUserMark> appUserMarkList = new ArrayList<>();
        for (IncreasedLimitList il : list) {
            IncreasedLimitLog iil = new IncreasedLimitLog();
            BeanUtils.copyBeanProp(iil, il);
            //提额前额度
            BigDecimal currentCreditLine = new BigDecimal(il.getCurrentCreditLine());
            //提额后额度
            BigDecimal increasedCreditLine = new BigDecimal(il.getIncreasedCreditLine());
            iil.setIncreasedAmt(increasedCreditLine.subtract(currentCreditLine));
            iil.setAdjustType(com.ruoyi.common.constant.Constants.RaiseLimit.ADJUST_TYPE_INNER);
            illList.add(iil);
            //提额成功后更新app_user_mark数据
            AppUserMark appUserMark = new AppUserMark();
            //总额度
            appUserMark.setCreditLine(increasedCreditLine);
            //本次提额额度
            appUserMark.setIncreasedAmt(increasedCreditLine.subtract(currentCreditLine));
            //提额时间
            appUserMark.setCustNo(il.getCustNo());
            appUserMarkList.add(appUserMark);
        }
        creditAccountMapper.insertIncreasedLimitLogBatch(illList);
        appUserMarkService.updateBatchByList(appUserMarkList);

        //更新提额客户的当前额度
        for (CreditAccount cAccount : creditAccountList) {
            for (IncreasedLimitList il : list) {
                if (cAccount.getCustNo().equals(il.getCustNo())) {
                    cAccount.setCreditLine(new BigDecimal(il.getIncreasedCreditLine()));
                }
            }
        }
        updateCreditLineBatch(creditAccountList);

        //短信群发
        Map<String, CreditAccount> creditAccountMap = creditAccountList.stream().collect(Collectors.toMap(CreditAccount::getCustNo, r -> r));
        List<Map<String, String>> increasedLimitPhone = appUserMapper.getIncreasedLimitPhone(custNosStr);
        increasedLimitPhone.forEach(r -> {
            if (!Func.hasEmpty(r.get("custNo"), r.get("phone"), r.get("countryCode"))) {
                CreditAccount account = creditAccountMap.get(r.get("custNo"));
                if (account != null) {
                    JSONObject param = new JSONObject();
                    param.put("newCreditLine", account.getCreditLine());
                    SmsSendData smsData = SmsSendData.builder().noticeType(BizConstants.SMS_NOTICE_TYPE_NOTICE)
                            .smsType("smsType").phoneNumber(r.get("phone")).countryCode(r.get("countryCode"))
                            .smsParam(param).smsType(BizConstants.SMS_TEMPLATE_INCREASE_CREDIT_LINE).build();
                    asyncService.sendSms(smsData);
                }
            }
        });


        //提额成功数据
        custNos = list.stream().map(p -> p.getCustNo()).collect(Collectors.toList());
        String successcustNos = StringUtils.join(custNos.toArray());
        errorMsgList.add("成功提额" + list.size() + "条数据, custNo=" + successcustNos);


        return errorMsgList;
    }

    /**
     * 检查导入提额名单对象必填字段
     *
     * @param il
     * @return
     */
    public boolean checkThisObjEmpty(IncreasedLimitList il) {
        if (StringUtils.isEmpty(il.getBatchNo()) || StringUtils.isEmpty(il.getCustNo())
                || StringUtils.isEmpty(il.getCustName()) || StringUtils.isEmpty(il.getCurrentCreditLine())
                || StringUtils.isEmpty(il.getIncreasedCreditLine()) || StringUtils.isEmpty(il.getIncreasedReason())
                || StringUtils.isEmpty(il.getPhone())) {
            return false;
        }
        return true;
    }

    /**
     * 检查导入提额名单BatchNo字段是否错误，每行一样
     *
     * @param list
     * @return
     */
    public boolean checkBatchNo(List<IncreasedLimitList> list) {
        String batchNo = list.get(0).getBatchNo();
        for (int i = 1; i < list.size(); i++) {
            if (!batchNo.equals(list.get(i).getBatchNo())) {
                return false;
            }
        }
        return true;
    }

}
